﻿using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace RabbitMQClient
{
    public partial class FrmMain : Form
    {
        public FrmMain()
        {
            InitializeComponent();
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            var factory = new ConnectionFactory()
            {
                VirtualHost = "/uis",
                HostName = txtIpAddress.Text,
                Port = int.Parse(txtPort.Text),
                UserName = txtUserName.Text,
                Password = txtPassword.Text
            };

            using (var connection = factory.CreateConnection())
            {
                using (var channel = connection.CreateModel())
                {
                    channel.QueueDeclare("RunQueue1", false, false, false, null);
                    var properties = channel.CreateBasicProperties();
                    properties.DeliveryMode = 2;
                    string message = "hello world"; //传递的消息内容
                    //生产消息
                    channel.BasicPublish("", "RunQueue1", properties, Encoding.UTF8.GetBytes(message)); 
                    Console.WriteLine($"Send:{message}");
                }
            }
        }

        private void btnConsumer_Click(object sender, EventArgs e)
        {
            Thread revMsg = new Thread(ReceiveMsgThread) { Name = "revMsg", IsBackground = true };
            revMsg.Start();
        }

        private void ReceiveMsgThread()
        {
            var factory = new ConnectionFactory();
            factory.VirtualHost = "/uis";
            factory.HostName = txtIpAddress.Text;
            factory.Port = int.Parse(txtPort.Text);
            factory.UserName = txtUserName.Text;
            factory.Password = txtPassword.Text;

            using (var connection = factory.CreateConnection())
            {
                using (var channel = connection.CreateModel())
                {
                    channel.QueueDeclare("RunQueue1", true, false, false, null);

                    //var consumer = new EventingBasicConsumer(channel);
                    var consumer = new QueueingBasicConsumer(channel);
                    channel.BasicConsume("RunQueue1", false, consumer);//消费消息

                    while (true)
                    {
                        //阻塞函数，获取队列中的消息  
                        var ea = (BasicDeliverEventArgs)consumer.Queue.Dequeue();//挂起的操作  
                        //模拟长时间运行  
                        Thread.Sleep(600);
                        byte[] body = ea.Body;

                        var message = Encoding.UTF8.GetString(body);
                        Console.WriteLine($"Received:{message}");

                        //发送应答包，消息持久化时候使用  
                        channel.BasicAck(ea.DeliveryTag, false);
                    }
                    //consumer.Received += (model, ea) =>
                    //{
                    //    var body = ea.Body;
                    //    var message = Encoding.UTF8.GetString(body);
                    //    Console.WriteLine($"Received:{message}");
                    //};
                }
            }
        }

        private void benPublish_Click(object sender, EventArgs e)
        {
            var factory = new ConnectionFactory()
            {
                VirtualHost = "/uis",
                HostName = txtIpAddress.Text,
                Port = int.Parse(txtPort.Text),
                UserName = txtUserName.Text,
                Password = txtPassword.Text
            };

            //创建一个链接
            using (var connection = factory.CreateConnection())
            {
                //创建一个信道
                using (var channel = connection.CreateModel())
                {
                    string exchangeName = "Efanout_test";
                    //定义一个交换机，且采用广播类型,并持久化该交换机  
                    channel.ExchangeDeclare(exchangeName, ExchangeType.Fanout,true);
                    //channel.ExchangeDeclare("publish-topic", "topic", true);

                    string smsqueue = channel.QueueDeclare("sms.message", true, false, false, null);//创建一个队列,第2个参数为true表示为持久队列  
                    //绑定到名字叫publish的exchange上  
                    channel.QueueBind(smsqueue, exchangeName, "sms");

                    string emailqueue = channel.QueueDeclare("email.message", true, false, false, null);//创建一个队列,第2个参数为true表示为持久队列  
                    channel.QueueBind(emailqueue, exchangeName, "email");

                    var properties = channel.CreateBasicProperties();
                    properties.DeliveryMode = 2;//1表示不持久,2.表示持久化  

                    string message = "hello world"; //传递的消息内容
                    //发送消息,这里指定了交换机名称,且routeKey会被忽略  
                    channel.BasicPublish(exchangeName, "sms", properties, Encoding.UTF8.GetBytes(message));  

                    Console.WriteLine($"Send:{message}");
                }
            }
        }

        ConnectionFactory runMqConn;
        IConnection connection;
        bool allowMsg;

        private void btnExchange_Click(object sender, EventArgs e)
        {
            //创建远程连接
            if (runMqConn == null)
            {
                runMqConn = new ConnectionFactory()
                {
                    VirtualHost = "/uis",
                    HostName = txtIpAddress.Text,
                    Port = int.Parse(txtPort.Text),
                    UserName = txtUserName.Text,
                    Password = txtPassword.Text
                };

                //创建连接对象
                connection = runMqConn.CreateConnection();
            }

            if (connection != null)
            {
                allowMsg = true;

                Thread familyThread = new Thread(GetFamilyMsg) { Name = "familyThread", IsBackground = true };
                familyThread.Start();
            }
        }

        /// <summary>
        /// 获取消息处理
        /// </summary>
        private void GetFamilyMsg()
        {
            //创建通道
            using (var channel = connection.CreateModel())
            {
                ShowMessage("开始创建Exchange");
                string exchangeName = "uis";
                //定义交换机
                channel.ExchangeDeclare(exchangeName, ExchangeType.Direct, true, false, null);
                //公平调用
                //channel.BasicQos(prefetchSize:0,prefetchCount:1,global:false);
                ShowMessage("开始创建订阅Queue");
                //定义消息队列
                string smsqueue = channel.QueueDeclare("192.168.0.11", true, false, false, null);

                //family  interact
                //绑定
                channel.QueueBind(smsqueue, exchangeName, "interact", null);
                //定义消费者
                var consumer = new EventingBasicConsumer(channel);

                while (allowMsg)
                {
                    //实现获取message处理事件
                    consumer.Received += (model, ea) =>
                    {
                        var body = ea.Body;
                        var message = Encoding.UTF8.GetString(body);

                        ShowMessage(string.Format("received : {0}", message));

                        //手动设置回复
                        //channel.BasicAck(deliveryTag: ea.DeliveryTag, multiple: false);
                    };
                    Thread.Sleep(300);
                    //设置手动回复认证 接受队列名称
                    channel.BasicConsume(smsqueue, true, consumer);
                }

                //另一个的参数
                //channel.BasicConsume(queue: "qfanout_test2", autoAck: false, consumer: consumer);
            }
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            allowMsg = false;
        }

        private int _msgLins = 0;
        private void ShowMessage(string msg)
        {
            if (txtMsg.InvokeRequired)
            {
                Action<string> ac = new Action<string>(ShowMessage);
                txtMsg.Invoke(ac, msg);
            }
            else
            {
                //当行数达到300，则清空文本框
                if (_msgLins == 300)
                {
                    txtMsg.Clear();
                    _msgLins = 0;
                }
                txtMsg.Text = txtMsg.Text + (DateTime.Now.ToString() + " " + "消息引擎：" + msg + "\r\n");
                txtMsg.SelectionStart = txtMsg.Text.Length;
                txtMsg.ScrollToCaret();

                _msgLins++;
            }
        }
    }
}
